/*
@title: Galacticats
@description: Galacticats is a puzzle-strategy game where you guide a space cat safely back to its spaceship while avoiding enemies. The enemies move in response to the player's movements, creating a challenging dynamic as you attempt to navigate through each level. Strategically plan your moves to avoid landing on the same squares as the enemies, ensuring the cat's safe return to the spaceship.
@author: adadyer
@tags: []
@addedOn: 2022-11-23

Get the Galacticat back to his ship. 

*/

const player = "p";
const portal = "o";
const space1 = "1";
const space2 = "2";
const spaceJunk = "j";
const enemy = "e";
const enemy2 = "f"
const enemy3 = "g";
const spaceship = "s";

// pretty art :3

setLegend(
  [ player, bitmap`
................
..CC........CC..
..CCC......CCCC.
.CC8CC....CC88C.
.C888CC...C888C.
.CCCCCCCCCCCCCC.
.CCCCCCCCCCCCCC.
.CC200CCCC200CC.
.CC200CCCC200CC.
.CCCCCCCCCCCCCC.
.CCCCCC88CCCCCC.
.CCCCCCCCCCCCCC.
.CC0000000000CC.
.CCCCCCCCCCCCCC.
.CCCCCCCCCCCCCC.
................`],
  [ portal, bitmap`
................
.HHHHHHHHHHHHHH.
.H888888888888H.
.H877777777778H.
.H875555555578H.
.H875000000578H.
.H875000000578H.
.H875000000578H.
.H875000000578H.
.H875000000578H.
.H875000000578H.
.H875555555578H.
.H877777777778H.
.H888888888888H.
.HHHHHHHHHHHHHH.
................`],
  [ space1, bitmap`
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000`],
  [ space2, bitmap`
0000000000002000
0200000000000000
0000000000000000
0000002000000000
0000000000000020
0000000000000000
0000000000000000
0000002000000000
0000000000002000
2000000000000000
0000000000000000
0000000000000000
0000000002000000
0002000000000000
0000000000000002
0000000000000000` ],
  [ spaceJunk, bitmap`
11111....1111111
11111....1111111
11111LLLL111FFFF
11111LLLL111FFFF
111FFFFF1111FFFF
...FFFFF1111FFFF
...FFFFF111111..
...LLLL111LLLLLL
FFFF...111LLLLLL
FFFFLLLL11LLLLLL
FFFFLLLL..LLLLLL
FFFFLLLFFFFFLLLL
1111LLLFFFFFLLLL
1111LLLFFFFFLLLL
1111...FFFFF....
1111...FFFFF....`], 
  [ enemy, bitmap`
................
.33..........33.
.3333.......333.
.38833.....3383.
.38883....33883.
.33333333333333.
.33333333333333.
.33333333333333.
.33300033000333.
.33333333333333.
.33333388333333.
.33333333333333.
.33333300333333.
.33333033033333.
.33333333333333.
................`],
  [ enemy2, bitmap`
................
.77..........77.
.777........777.
.7877......7787.
.7887......7887.
.77777777777777.
.77777777777777.
.77777777777777.
.77700077000777.
.77777777777777.
.77777788777777.
.77777777777777.
.77777700777777.
.77777077077777.
.77777777777777.
................`],
  [ enemy3, bitmap`
......444.......
......4884......
......48444.....
......444444....
......4440444...
.....444044444..
444444444444444.
488444444444444.
484440448444444.
.4440444400044..
..44444440444...
...444444044....
....4444444.....
.....44444......
......444.......
................`],
  [ spaceship, bitmap`
.......33.......
......3333......
.....333333.....
.....333333.....
....33333333....
....32222223....
....32222223....
....32222223....
....32222223....
....32222223....
....33233233....
...3332332333...
...3332332333...
...3332332333...
..333333333333..
..3333.33.3333..`]
);

setBackground(space2)

// moosic

const gameMusic = tune`
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: c4~150.7537688442211 + e4~150.7537688442211 + g4~150.7537688442211 + g5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: d4~150.7537688442211 + f4~150.7537688442211 + a4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: e4~150.7537688442211 + g4~150.7537688442211 + b4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: e4~150.7537688442211 + g4~150.7537688442211 + b4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: e4~150.7537688442211 + g4~150.7537688442211 + b4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: e4~150.7537688442211 + g4~150.7537688442211 + b4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: e4~150.7537688442211 + g4~150.7537688442211 + b4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: b4~150.7537688442211 + g4~150.7537688442211 + e4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: b4~150.7537688442211 + g4~150.7537688442211 + e4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: b4~150.7537688442211 + g4~150.7537688442211 + e4~150.7537688442211 + b5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211,
150.7537688442211: a4~150.7537688442211 + f4~150.7537688442211 + d4~150.7537688442211 + a5^150.7537688442211`;

const ohNo = tune`
206.18556701030928,
103.09278350515464: b4/103.09278350515464 + c5-103.09278350515464,
103.09278350515464: b4/103.09278350515464 + c5-103.09278350515464,
103.09278350515464: b4/103.09278350515464 + c5-103.09278350515464,
103.09278350515464: b4/103.09278350515464 + c5-103.09278350515464,
103.09278350515464: g4/103.09278350515464 + a4-103.09278350515464,
103.09278350515464: e4/103.09278350515464 + f4-103.09278350515464,
103.09278350515464: c4/103.09278350515464 + d4-103.09278350515464,
2371.134020618557`;

const meow = tune`
638.2978723404256,
159.5744680851064: f4~159.5744680851064 + g4~159.5744680851064 + a4~159.5744680851064 + b4~159.5744680851064 + c5~159.5744680851064,
159.5744680851064: b4~159.5744680851064,
159.5744680851064: a4~159.5744680851064,
159.5744680851064: b4~159.5744680851064,
159.5744680851064: c5~159.5744680851064 + b4~159.5744680851064 + a4~159.5744680851064 + g4~159.5744680851064 + f4~159.5744680851064,
159.5744680851064,
159.5744680851064: c5-159.5744680851064 + b4-159.5744680851064 + a4-159.5744680851064 + g4-159.5744680851064 + f4-159.5744680851064,
159.5744680851064: c5-159.5744680851064 + a4-159.5744680851064 + f4-159.5744680851064,
159.5744680851064: c5-159.5744680851064 + a4-159.5744680851064 + f4-159.5744680851064,
159.5744680851064,
159.5744680851064: c5^159.5744680851064 + b4^159.5744680851064 + a4^159.5744680851064 + g4^159.5744680851064 + f4^159.5744680851064,
159.5744680851064: f4^159.5744680851064 + c5^159.5744680851064,
159.5744680851064: f4^159.5744680851064 + g4^159.5744680851064 + a4^159.5744680851064 + b4^159.5744680851064 + c5^159.5744680851064,
159.5744680851064,
159.5744680851064: c5/159.5744680851064 + b4/159.5744680851064 + a4/159.5744680851064 + g4/159.5744680851064 + f4/159.5744680851064,
159.5744680851064: g4/159.5744680851064,
159.5744680851064: a4/159.5744680851064,
159.5744680851064: g4/159.5744680851064,
159.5744680851064: f4/159.5744680851064 + g4/159.5744680851064 + a4/159.5744680851064 + b4/159.5744680851064 + c5/159.5744680851064,
1436.1702127659576`;

// level maps 

let level = 0;
const levels = [
  map`
p.......
........
........
........
........
...e....
........
.......o`,
  map`
p....je..j..
jjj..j...j..
.....je..j..
.....j...j..
.....je..j..
..j..j...j..
..j.........
..j.........
..jjjjjjjj..
...........o`,
  map`
p.....e....j
jjjj.jjjjjjj
e..........j
.jjj.jjjjjjj
...j.......j
.j.jjj.j.j.j
.j.....j.j..
.jjjjjjj.jjj
..j..j......
.....j..e..o`,
  map `
p...........
............
..jjj...jjj.
..j.......j.
..j.e...e.j.
..j.......j.
..j...f...j.
..j.......j.
..j.......j.
..j...o...j.`,
  map`
p.....e..j..
.........j..
jjjjjjj..j..
.........j..
f..j.....j..
...j.....j..
...j.....j.f
...j........
...jjjjjjjjj
...........o`,
  map `
fpf..j....e.
.....j......
.....j......
.....j.jjjjj
............
........ej.o
............
.....j.jjjjj
.....j......
.....j....e.`,
  map`
....j...e..o
....j...e...
f...j.....ee
e...j.......
....j.......
............
....j.jjjjjj
............
............
p.....ef....`,
  map`
o.j..j..j.o
.....j.....
jjj.....jjj
....jfj....
e....p....e
....jfj....
jjj.....jjj
.....j.....
o.j..j..j.o`,
  map`
g..p...j..
.......j..
.......j..
.......j..
..........
.........o`,
  map`
..gjpj...
.........
....e....
.........
.........
....o....`,
  map`
g..p.j..o.
...g.j....
.....j....
.....j.jjj
.jjjjj...g
....gj....
..j..j..j.
..j..j..j.
..j..j..j.
..j.....j.`,
  map`
j....o....j
.j.......j.
..j.....j..
...f...f...
.....g.....
..g..p..g..
.....g.....
...f...f...
..j.....j..
.j.......j.
j....o....j`,
  map`
p...s`
  
];
const theEnd = map`
...........
...........
...........
.....p.....
...........
...........`

setMap(levels[level]);

// handling solids, pushables

setSolids([player, spaceJunk]);

// handle player and enemy movement

onInput("w", () => {
  const p = getFirst(player);
  let ens = getAll(enemy)
  let en2s = getAll(enemy2)
  let en3s = getAll(enemy3)
  p.y -= 1
  ens.forEach( en => {
    en.y += 1
  })
  en2s.forEach( en2 => {
    en2.y -= 1
  })
  en3s.forEach( en3 => {
    en3.y -= 1
    en3.x -= 1
  })
});

onInput("s", () => {
  const p = getFirst(player);
  let ens = getAll(enemy)
  let en2s = getAll(enemy2)
  let en3s = getAll(enemy3)
  p.y += 1
  ens.forEach( en => {
    en.y -= 1
  })
  en2s.forEach( en2 => {
    en2.y += 1
  })
  en3s.forEach( en3 => {
    en3.y += 1
    en3.x += 1
  })
});

onInput("a", () => {
  const p = getFirst(player);
  let ens = getAll(enemy)
  let en2s = getAll(enemy2)
  let en3s = getAll(enemy3)
  p.x -= 1
  ens.forEach( en => {
    en.x += 1
  })
  en2s.forEach( en2 => {
    en2.x -= 1
  })
  en3s.forEach( en3 => {
    en3.y += 1
    en3.x -= 1
  })
});

onInput("d", () => {
  const p = getFirst(player);
  let ens = getAll(enemy)
  let en2s = getAll(enemy2)
  let en3s = getAll(enemy3)
  p.x += 1
  ens.forEach( en => {
    en.x -= 1
  })
  en2s.forEach( en2 => {
    en2.x += 1
  })
  en3s.forEach( en3 => {
    en3.y -= 1
    en3.x += 1
  })
});

// game loop


let playback = playTune(gameMusic, Infinity)

afterInput(() => {

  const tilesWithPlayer = tilesWith(player).length;
  
  const tilesWithPlayerAndPortal = tilesWith(player, portal).length;

  if (tilesWithPlayer === tilesWithPlayerAndPortal) {
    level = level + 1;

    const currentLevel = levels[level];

    if (currentLevel !== undefined) {
      setMap(currentLevel);
    } else {
      setMap(levels[0])
    }

  }

});


afterInput(() => {
  const tilesWithPlayerAndEnemies = tilesWith(enemy, player).length;
  const tilesWithPlayerAndEnemies2 = tilesWith(enemy2, player).length;
  const tilesWithPlayerAndEnemies3 = tilesWith(enemy3, player).length;
  


  if (tilesWithPlayerAndEnemies) {

    playTune(ohNo)
    
    level -= 1;

    const currentLevel = levels[level];

    if (currentLevel !== undefined) {
      setMap(currentLevel);
    } else {
      setMap(levels[0])
    }

  }

  if (tilesWithPlayerAndEnemies2) {
    playTune(ohNo)
    
    level -= 1;

    const currentLevel = levels[level];

    if (currentLevel !== undefined) {
      setMap(currentLevel);
    } else {
      setMap(levels[0])
    }

  }

  if (tilesWithPlayerAndEnemies3) {
    playTune(ohNo)
    
    level -= 1;

    const currentLevel = levels[level];

    if (currentLevel !== undefined) {
      setMap(currentLevel);
    } else {
      setMap(levels[0])
    }

  }
})

afterInput(() => {
  const tilesWithPlayerAndShip = tilesWith(spaceship, player).length;
  if (tilesWithPlayerAndShip) {
    const currentLevel = theEnd
    setMap(currentLevel)
    playback.end()
    playTune(meow)
    addText("You win!", { 
      y: 3,
      color: color`6`
    })
  }
})
